<?php

namespace App\Http\Controllers\Api;

use App\Exceptions\StandardException;
use App\Library\OSS;
use App\Modules\Order\Models\ChangeOrderPrice;
use App\Modules\Order\Models\Order;
use App\Modules\Package\Models\PackageAttr;
use App\Modules\Package\Models\PackageAttrValue;
use App\Modules\Package\Models\PackageSpec;
use App\Modules\Rebate\Jobs\RebateJob;
use App\Modules\Rebate\Models\Rebate;
use App\Modules\Rebate\NumberRank;
use App\Modules\Rebate\Rank;
use App\Modules\Rebate\RebateRank;
use App\Modules\Shop\Manager;
use App\Modules\Shop\Shop;
use App\Modules\User\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Overtrue\LaravelWeChat\Facade as EasyWeChat;

class ManageController extends ApiController
{
    public function getOrders(Request $request)
    {
        $this->validate($request, [
            'shop_id' => 'nullable|array',
            'start' => 'nullable|date',
            'end' => 'nullable|date',
            'referrer_id' => 'nullable|integer',
            'user_id' => 'nullable|integer',
            'offset' => 'nullable|integer',
            'count' => 'nullable|integer',
            'referrer_level' => 'nullable|integer',
            'name' => 'nullable|string',
        ]);

        $start = $request->input('start');
        $end = $request->input('end');
        $userId = $request->input('user_id');
        $offset = $request->input('offset', 0);
        $count = $request->input('count', 10);
        $referrerId = $request->input('referrer_id');
        $referrerLevel = $request->input('referrer_level');
        $shopId = $request->input('shop_id');
        $name = $request->input('name');

        $query = Order::query()
            ->orderBy('created_at', 'desc')
            ->offset($offset)
            ->limit($count);
        if (!empty($shopId)) {
            $query->whereIn('shop_id', $shopId);
        }
        if (!empty($start)) {
            $query->where('created_at', '>=', $start);
        }
        if (!empty($name)) {
            $query->where(function ($q) use ($name) {
                return $q->where('name', 'like', '%' . $name . "%")
                    ->orWhere('mobile', 'like', "%" . $name . "%");
            });
        }
        if (!empty($end)) {
            $query->where('created_at', '<=', $end);
        }
        if (!empty($userId)) {
            $query->where('user_id', $userId);
        }

        if (!empty($referrerId)) {
            $query->where('referrer_id', $referrerId);
        }
        if (!empty($referrerLevel)) {
            $query->where('referrer_level', $referrerLevel);
        }
        $order = $query->get();
        $users = User::query()
            ->whereIn('id', array_merge($order->pluck('user_id')->all(), $order->pluck('referrer_id')->all()))
            ->get()
            ->keyBy('id');
        $shops = Shop::query()->whereIn('id', $order->pluck('shop_id')->all())->get()->keyBy('id');
        $rebates = Rebate::query()
            ->where('origin', Order::class)
            ->whereIn('link_id', $order->pluck('id')->all())
            ->get()
            ->keyBy('order_id');
        $re = $order->map(function ($item) use ($users, $shops, $rebates) {
            $user = $users->get($item->user_id);
            $referrer = $users->get($item->referrer_id);
            $shop = $shops->get($item->shop_id);
            $rebate = $rebates->get($item->id);
            $rebateStatus = null;
            if (!is_null($rebate)) {
                if ($rebate->status == Rebate::STATUS_FINISH) {
                    $rebateStatus = Rebate::$withdrawalStatusShow[$rebate->withdrawal_status];
                } else {
                    $rebateStatus = Rebate::$withdrawalStatusShow[$rebate->status];
                }
            }
            return [
                'id' => $item->id,
                'user_id' => $item->user_id,
                'name' => $item->name,
                'nickname' => $user['nickname'],
                'type' => $item->type,
                'cover' => $item->cover,
                'title' => $item->title,
                'link_id' => $item->link_id,
                'number' => $item->number,
                'coupon_pay' => $item->coupon_pay,
                'discount_amount' => $item->discount_amount,
                'refund_fee' => $item->refund_fee,
                'price' => $item->price,
                'original_price' => $item->original_price,
                'referrer_id' => $item->referrer_id,
                'referrer_level' => $item->referrer_level,
                'referrer_nickname' => empty($item->referrer_id) ? null : $referrer->nickname,
                'referrer_name' => empty($item->referrer_id) ? null : $referrer->name,
                'status' => $item->status,
                'is_finish' => $item->is_finish,
                'delivery' => $item->delivery,
                'is_comment' => $item->is_appraised,
                'mobile' => $item->mobile,
                'address' => $item->address,
                'detail' => $item->detail,
                'created_at' => $item->created_at,
                'gift' => $item->gift,
                'shop' => $shop->name,
                'buyer_confirm' => $item->buyer_confirm,
                'is_prepay' => $item->is_prepay,
                'final_payment' => $item->final_payment,
                'rebate_status' => $rebateStatus,
                'buyer_remark' => $item->buyer_remark,
                'is_balance' => $item->is_balance,
                'balance_pay' => $item->balance_pay,
            ];
        });
        return $this->success($re ?? []);
    }

    public function finalPayment(Request $request)
    {
        $this->validate($request, [
            'id' => 'required|integer',
        ]);
        $id = $request->input('id');
        $shopId = $request->input('shop_id');
        $query = Order::query()
            ->where('id', $id);

        if (!empty($shopId)) {
            $query->whereIn('shop_id', $shopId);
        }
        $order = $query->first();
        $order->update([
            'offline_pay' => $order->getPrice(),
            'final_payment' => 1,
        ]);
        /**
         *  临洮：订单完成
         *  模板ID：z5lZEXqBy0ZSy3OuHPmurQGDP9C2tChEDDKTRxm9i7M
         *  格式：
         * {{first.DATA}}
         * 订单号：{{keyword1.DATA}}
         * 完成状态：{{keyword2.DATA}}
         * 完成时间：{{keyword3.DATA}}
         * {{remark.DATA}}
         */
        $user = User::query()->where("id", $order->user_id)->first();
        $sendData = [$user->openid, $order->id, "订单已完成", date("Y年m月d日 H时i分s秒")];
        if ($order->delivery == 0 && $order->is_prepay == 1) { //到店自取-定金支付
            sendMessage(12, $sendData);
        } elseif ($order->delivery > 0 && $order->is_prepay == 1) {//物流发货-定金支付
            sendMessage(13, $sendData);
        }
        return $this->success();
    }

    public function cancelFinalPayment(Request $request)
    {
        $this->validate($request, [
            'id' => 'required|integer',
        ]);
        $id = $request->input('id');
        $shopId = $request->input('shop_id');
        $query = Order::query()
            ->where('id', $id);
        if (!empty($shopId)) {
            $query->whereIn('shop_id', $shopId);
        }
        $order = $query->first();
        if (is_null($order)) {
            return $this->fail('订单错误');
        }
        $order->update([
            'final_payment' => 0,
        ]);
        return $this->success();
    }

    public function deliver(Request $request)
    {
        $this->validate($request, [
            'id' => 'required|integer'
        ]);
        $id = $request->input('id');
        $shopId = $request->input('shop_id');
        $query = Order::query()
            ->where('delivery', 1)
            ->where('id', $id);
        if (!empty($shopId)) {
            $query->whereIn('shop_id', $shopId);
        }
        $query->update([
            'delivery' => 2,
        ]);
        /**
         *  临洮：已发货
         *  模板ID：z5lZEXqBy0ZSy3OuHPmurQGDP9C2tChEDDKTRxm9i7M
         *  格式：
         * {{first.DATA}}
         * 订单号：{{keyword1.DATA}}
         * 完成状态：{{keyword2.DATA}}
         * 完成时间：{{keyword3.DATA}}
         * {{remark.DATA}}
         */
        $order = Order::query()->where('id', $id)->first();
        $user = User::query()->where("id", $order->user_id)->first();

        $sendData = [$user->openid, $order->id, "订单已发货", date("Y年m月d日 H时i分s秒")];
        if ($order->delivery == 0 && $order->is_prepay == 1) { //到店自取-定金支付
        } elseif ($order->delivery == 0 && $order->is_prepay == 0) {//到店自取-全款支付
        } elseif ($order->delivery > 0 && $order->is_prepay == 1) {//物流发货-定金支付
            sendMessage(16, $sendData);
        } elseif ($order->delivery > 0 && $order->is_prepay == 0) {//物流发货-全款支付
            sendMessage(17, $sendData);
        }
        return $this->success();
    }

    public function orderFinish(Request $request)
    {
        $this->validate($request, [
            'id' => 'required|integer',
        ]);
        $id = $request->input('id');
        $shopId = $request->input('shop_id');
        $query = Order::query()
            ->where('id', $id);
        if (!empty($shopId)) {
            $query->whereIn('shop_id', $shopId);
        }
        $order = $query->first();
        if (is_null($order)) {
            return $this->fail('订单错误');
        }
        $order->update([
            'buyer_confirm' => 1,//买家确认
        ]);
        $order->finish();
        return $this->success();
    }

    public function changePrice(Request $request)
    {
        $this->validate($request, [
            'id' => 'required|integer',
            'price' => 'required|integer',
        ]);
        $id = $request->input('id');
        $shopId = $request->input('shop_id');
        $price = $request->input('price');
        $user = $this->getUser();

        $query = Order::query()
            ->where('id', $id);
        if (!empty($shopId)) {
            $query->whereIn('shop_id', $shopId);
        }
        $order = $query->first();
        if ($order->type == Order::TYPE_GOOD) {
            if (count($order->detail) > 1) {
                return $this->fail('有多个免费购商品, 不能修改价格');
            }
        }
        if ($order->is_prepay) {
            $newNo = $order->pay_no;
            $data = [
                'original_price' => $price,
                'discount_amount' => 0,
                'coupon_pay' => 0,
            ];
        } else {
            $newNo = Order::getPayNo();
            $data = [
                'pay_no' => $newNo,
                'price' => $price,
                'original_price' => $price,
                'discount_amount' => 0,
                'coupon_pay' => 0,
            ];
        }
        DB::beginTransaction();
        ChangeOrderPrice::query()
            ->create([
                'old_pay_no' => $order->pay_no,
                'new_pay_no' => $newNo,
                'old_price' => $order->price,
                'new_price' => $price,
                'reason' => '',
                'operator_id' => $user->id,
            ]);
        $order->update($data);

        /**
         *  临洮：订单修改通知
         *  模板ID：ONFfIY2RQ4lrxaCtFxDgdBWP4MT-hRtKm7YZEtqwf_8
         *  格式：
         * {{first.DATA}}
         * 修改类型：{{keyword1.DATA}}
         * 修改明细：{{keyword2.DATA}}
         * 修改时间：{{keyword3.DATA}}
         * {{remark.DATA}}
         */
        $price = $price / 100;
        // $sendData = [$user->openid, "价格修改", "您的订单价格已修改为：{$price} 元", date("Y年m月d日 H时i分s秒")];
        $sendUser = User::query()->find($order->user_id);
        $sendData = [$sendUser->openid, "价格修改", "您的订单价格已修改为：{$price} 元", date("Y年m月d日 H时i分s秒")];
        if ($order->delivery == 0 && $order->is_prepay == 1) { //到店自取-定金支付
            sendMessage(2, $sendData);
        } elseif ($order->delivery == 0 && $order->is_prepay == 0) {//到店自取-全款支付
            sendMessage(3, $sendData);
        } elseif ($order->delivery > 0 && $order->is_prepay == 1) {//物流发货-定金支付
            sendMessage(4, $sendData);
        } elseif ($order->delivery > 0 && $order->is_prepay == 0) {//物流发货-全款支付
            sendMessage(5, $sendData);
        }
        DB::commit();
        return $this->success();
    }

    public function give(Request $request)
    {
        $this->validate($request, [
            'id' => 'required|integer',
            'spec' => 'required|array',
        ]);
        $id = $request->input('id');
        $spec = $request->input('spec');
        $shopId = $request->input('shop_id');

        $query = Order::query()
            ->where('id', $id);
        if (!empty($shopId)) {
            $query->whereIn('shop_id', $shopId);
        }
        $order = $query->first();
        $packageId = $order->link_id;
        $specId = array_column($spec, 'id');
        $packageSpec = PackageSpec::query()
            ->where('package_id', $packageId)
            ->whereIn('id', $specId)
            ->get()
            ->keyBy('id');
        if ($packageSpec->isEmpty()) {
            throw new StandardException("套系信息错误");
        }
        $spec = collect($spec)->keyBy('id');
        $attrValue = PackageAttrValue::query()
            ->whereIn('id', $packageSpec->pluck('attr_value_id')->all())
            ->get()
            ->keyBy('id');
        $attr = PackageAttr::query()
            ->whereIn('id', $attrValue->pluck('package_attr_id')->all())
            ->get()
            ->keyBy('id');
        $gift = $packageSpec->map(function ($item) use (&$selectPrice, $attr, $attrValue, $spec) {
            $tmp = $attrValue->get($item->attr_value_id);
            $selectPrice += $tmp->selling_price * $spec->get($item->id)['number'];
            return [
                'id' => $item->id,
                'attr' => $attr->get($tmp->package_attr_id)->name,
                'attr_id' => $tmp->package_attr_id,
                'attr_value_id' => $item->attr_value_id,
                'attr_value' => $tmp->value,
                'price' => $tmp->selling_price,
                'cover' => OSS::instance()->getUrl($tmp->cover),
                'number' => $spec->get($item->id)['number'],
            ];
        })->values();
        $order->update([
            'gift' => $gift,
        ]);
        return $this->success();
    }

    public function getStatistics(Request $request)
    {
        $start = $request->input('start');
        $end = $request->input('end');
        $userId = $request->input('user_id');
        $referrerId = $request->input('referrer_id');
        $referrerLevel = $request->input('referrer_level');
        $shopId = $request->input('shop_id');
        $name = $request->input('name');

        $re = [
            'order_number' => 0,
            'money' => 0,
        ];
        $query = Order::query()
            ->where('status', Order::STATUS_PAID);

        if (!empty($shopId)) {
            $query->whereIn('shop_id', $shopId);
        }
        if (!empty($name)) {
            $query->where(function ($q) use ($name) {
                return $q->where('name', 'like', '%' . $name . "%")
                    ->orWhere('mobile', 'like', "%" . $name . "%");
            });
        }
        if (!empty($start)) {
            $query->where('created_at', '>=', $start);
        }
        if (!empty($end)) {
            $query->where('created_at', '<=', $end);
        }
        if (!empty($userId)) {
            $query->where('user_id', $userId);
        }
        if (!empty($referrerId)) {
            $query->where('referrer_id', $referrerId);
        }
        if (!empty($referrerLevel)) {
            $query->where('referrer_level', $referrerLevel);
        }
        $re['order_number'] = $query->count();

        $query = Rebate::query()
            ->join('orders', function ($q) {
                return $q->on('orders.id', '=', 'rebates.link_id')
                    ->where('origin', Order::class);
            });
        if (!empty($shopId)) {
            $query->whereIn('orders.shop_id', $shopId);
        }
        if (!empty($start)) {
            $query->where('rebates.created_at', '>=', $start);
        }
        if (!empty($end)) {
            $query->where('rebates.created_at', '<=', $end);
        }
        if (!empty($userId)) {
            $query->where('orders.user_id', $userId);
        }
        if (!empty($referrerId)) {
            $query->where('orders.referrer_id', $referrerId);
        }
        if (!empty($referrerLevel)) {
            $query->where('rebates.level', $referrerLevel);
        }

        $re['rebate_number'] = $query->count();
        $re['money'] = $query->sum('money');
        return $this->success($re ?? []);
    }

    public function getRebateList(Request $request)
    {
        $this->validate($request, [
            'referrer_id' => 'nullable|integer',
            'referrer_level' => 'nullable|integer',
            'start' => 'nullable|date',
            'end' => 'nullable|date',
            'offset' => 'nullable|integer',
            'count' => 'nullable|integer',
        ]);
        $start = $request->input('start');
        $end = $request->input('end');
        $shopId = $request->input('shop_id');
        $referrerId = $request->input('referrer_id');
        $referrerLevel = $request->input('referrer_level');
        $offset = $request->input('offset', 0);
        $count = $request->input('count', 10);

        $query = Rebate::query()
            ->offset($offset)
            ->limit($count);
        if (!empty($shopId)) {
            $query->whereIn('shop_id', $shopId);
        }
        if (!empty($start)) {
            $query->where('created_at', '>=', $start);
        }

        if (!empty($end)) {
            $query->where('created_at', '<=', $end);
        }
        if (!empty($referrerId)) {
            $query->where('user_id', $referrerId);
        }
        if (!empty($referrerLevel)) {
            $query->where('level', $referrerLevel);
        }
        $data = $query
            ->orderBy('created_at', 'desc')
            ->get();
        $users = User::query()->whereIn('id', array_merge($data->pluck('user_id')->all(), $data->pluck('buyer_id')->all()))->get()->keyBy('id');
        $shops = Manager::getShop($data->pluck('shop_id')->all());
        $orders = Order::query()->whereIn('id', $data->pluck('link_id')->all())->get()->keyBy('id');
        $re = $data->map(function ($item) use ($users, $shops, $orders) {
            $orderUser = $users->get($item->buyer_id);
            $rebateUser = $users->get($item->user_id);
            $order = $orders->get($item->link_id);
            $shop = $shops->get($item->shop_id);
            return [
                'id' => $item->id,
                'nickname' => $orderUser->nickname,
                'name' => $order->name ?? $orderUser->name,
                'avatar' => $orderUser->avatar,
                'title' => $item->title,
                'shop' => $shop->name,
                'created_at' => $item->created_at,
                'price' => $item->price,
                'referrer' => $rebateUser->name,
                'rebate' => $item->money,
                'identity' => User::$levelShow[$rebateUser->level],
            ];
        });
        return $this->success($re ?? []);
    }


    public function getUserData(Request $request)
    {
        $this->validate($request, [
            'shop_id' => 'nullable|array',
            'level' => 'required|integer',
            'user_id' => 'nullable|integer',
            'offset' => 'nullable|integer',
            'count' => 'nullable|integer',
            'start' => 'nullable|date',
            'end' => 'nullable|date',
            'search' => 'nullable|string',
        ]);
        $start = $request->input('start');
        $end = $request->input('end');
        $shopId = $request->input('shop_id');
        $level = $request->input('level');
        $offset = $request->input('offset', 0);
        $count = $request->input('count', 10);
        $userId = $request->input('user_id');
        $search = $request->input('search');
        $query = Order::query()
            ->join('users', 'users.id', '=', 'orders.referrer_id')
            ->leftJoin('rebates', function ($q) use ($level) {
                return $q->on('rebates.link_id', '=', 'orders.id')
                    ->where('rebates.level', '=', $level)
                    ->whereRaw('rebates.user_id = orders.referrer_id');
            })
            ->where('orders.referrer_level', $level)
            ->where('orders.status', Order::STATUS_PAID)
            ->when(!empty($search), function ($query) use ($search) {
                return $query->where('users.name', 'like', "%{$search}%");
            });
        $query2 = (clone $query)->selectRaw('distinct orders.referrer_id, orders.shop_id');

        $query->offset($offset)->limit($count);
        if (!empty($shopId)) {
            $query->whereIn('orders.shop_id', $shopId);
        }

        if (!empty($start)) {
            $query->where('orders.created_at', '>=', $start);
        }
        if (!empty($end)) {
            $query->where('orders.created_at', '<=', $end);
        }
        if (!empty($userId)) {
            $query->where('orders.referrer_id', $userId);
        }


//        Log::info($referrerShop);
        $data = $query
            ->selectRaw('sum(rebates.money) as money, count(distinct orders.id) as order_number, orders.referrer_id, users.name, users.level, users.avatar, users.position')
            ->groupBy('referrer_id')
            ->get();
        $shopIds = $query2->whereIn('orders.referrer_id', $data->pluck('referrer_id')->toArray())->get();
        $shops = Shop::query()->whereIn('id', $shopIds->pluck('shop_id')->all())->get()->keyBy('id');
        $referrerShop = [];
        foreach ($shopIds as $value) {
            if (empty($shopId) || in_array($value->shop_id, $shopId)) {
                $referrerShop[$value->referrer_id][] = $shops->get($value->shop_id, collect())->only('id', 'name');
            }

        }

        $users = User::query()->whereIn('id', $data->pluck('referrer_id')->all())->get()->keyBy('id');
        $re = $data->map(function ($item) use ($referrerShop, $users) {
            $user = $users->get($item->referrer_id);
            $shop = $referrerShop[$item->referrer_id] ?? [];
            return [
                'user_id' => $item->referrer_id,
                'nickname' => $user->name,
                'level' => $user->level,
                'avatar' => $user->avatar,
//                'shop_id' => $item->shop_id,
                'shop' => $shop,
                'identity' => User::$levelShow[$user->level],
                'position' => $user->position,
                'order_number' => $item->order_number,
                'rebate' => $item->money ?? 0,
            ];
        });
        return $this->success($re ?? []);
    }

    public function getRank(Request $request)
    {
        $this->validate($request, [
            'level' => 'required|integer',
            'offset' => 'nullable|integer',
            'count' => 'nullable|integer',
            'interval' => 'required|string',
            'type' => 'required|string',
        ]);
        $offset = $request->input('offset');
        $count = $request->input('count');
        $level = $request->input('level');
        $type = $request->input('type');
        $shopId = $request->input('shop_id');
        $interval = $request->input('interval');
        switch ($interval) {
            case 'monthly':
                $time = now()->startOfMonth()->toDateTimeString();
                break;
            case 'quarterly ':
                $time = now()->startOfQuarter()->toDateTimeString();
                break;
            default:
                $time = now()->startOfYear()->toDateTimeString();
                break;
        }
        $rank = \App\Modules\System\Models\Rank::query()
            ->join('users', 'users.id', '=', 'ranks.user_id')
            ->when(!empty($shopId), function ($query) use ($shopId) {
                return $query->whereIn('ranks.shop_id', $shopId);
            })
            ->where('ranks.level', $level)
            ->where('users.level', $level)
            ->where('date', '>=', $time)
            ->when($type == 'money', function ($query) use ($type) {
                return $query->selectRaw('sum(money) as score, user_id');
            }, function ($query) use ($type) {
                return $query->selectRaw('sum(number) as score, user_id');
            })
            ->groupBy('user_id')
            ->orderBy('score', 'desc')
            ->offset($offset)
            ->limit($count)
            ->get();

        $users = User::query()->find($rank->pluck('user_id')->all())->keyBy('id');
        $referrer = collect();
        if ($level == 2) {
            $referrer = User::query()->find($users->pluck('referrer_id')->all())->keyBy('id');
        }
        $re = $rank->map(function ($item) use ($users, $level, $referrer) {
            $user = $users->get($item->user_id);
            return [
                'nickname' => $user->nickname,
                'name' => $user->name,
                'avatar' => $user->avatar,
                'score' => $item->score,
                'referrer' => $level == 2 ? $referrer->get($user->referrer_id)->nickname : null,
            ];
        });
        return $this->success($re ?? []);
    }
}
